// import {hasProperty} from "@/utils/utils";
import moment from "moment";

interface BookmarkObj {
    title?: string;
    path?: string;
    datetime?: string;
    children?: BookmarkObj[] | null;
    url?: string;
    parent?: BookmarkObj | null;
}


class Bookmark {
    title: string;
    path: string;
    datetime?: string;
    children: Bookmark[];
    url?: string;
    parent?: Bookmark | null;

    constructor(title?: string, path?: string, children?: Bookmark[], url?: string, datetime?: string, parent?: Bookmark | null) {
        this.title = title || '';
        this.path = path || '';
        this.children = children || [];
        this.url = url || "";
        this.datetime = datetime || moment().format("YYYY-MM-DD HH:mm:ss");
        this.parent = parent || null;
    }

    /**
     * 转成object
     */
    toObj(): {
        title: string;
        path: string;
        datetime?: string;
        children: ReturnType<Bookmark['toObj']>[];
        url?: string;
        // parent?: Bookmark | null;
    } {
        return {
            title: this.title,
            path: this.path,
            datetime: this.datetime,
            children: this.children.map(child => child.toObj()),
            url: this.url,
            // parent: this.parent,
        }
    }

    /**
     * 从object转成书签
     * @param obj
     * @param parent
     */
    static fromObject(obj: BookmarkObj, parent?: Bookmark | null): Bookmark {
        let bookmark = new Bookmark(
            obj.title,
            obj.path,
            [],
            obj.url,
            obj.datetime,
            parent,
        );
        if (obj.children) {
            bookmark.children = obj.children.map((child: BookmarkObj) => Bookmark.fromObject(child, bookmark))
        }
        return bookmark;
    }

    /**
     * 合并
     * todo
     * @param bookmark
     */
    merge(bookmark: Bookmark) {

    }
}


/**
 * 获取书签路径
 * @param title
 * @param parentBookmark
 * @param isDir
 */
function getBookmarkPath(title: string, parentBookmark: Bookmark | null, isDir: boolean): string {
    let parentPath = parentBookmark && parentBookmark.path? parentBookmark.path : "";
    parentPath = parentPath.endsWith("/")? parentPath.slice(0, -1) : parentPath;
    let path = [parentPath, title].join("/");
    if (isDir) {
        path += "/";
    }
    // console.log("getBookmarkPath", path, "， ", title, "， ", parentBookmark, "， ", isDir);
    return path;
}


/**
 * 整理书签
 * @param bookmarks
 * @param pathSet
 * @param parent
 */
function cleanupBookmarks(bookmarks: Bookmark[], pathSet: Record<string, Bookmark>, parent: Bookmark | null): Bookmark[] {
    let needDelBookmarkIndex: number[] = [];
    bookmarks.forEach(function (bookmark, i) {
        let source_path = bookmark.path;
        bookmark.path = getBookmarkPath(bookmark.title, parent, bookmark.url === "");
        // console.log("原路径和新路径", source_path, bookmark.path);
        let existBookmark = pathSet[bookmark.path];
        // if (hasProperty(pathSet, bookmark.path)) {
        if (existBookmark) {
            // 如果路径已经存在
            // let existBookmark = pathSet[bookmark.path];
            if (!existBookmark.url) {
                // 如果已存在的书签中的url为空，说明这个书签是文件夹
                if (!bookmark.url) {
                    // 如果书签的url也不存在，说明两个书签都是文件夹，则合并
                    // let eBDatetime = existBookmark.datetime ? existBookmark.datetime : moment().format('YYYY-MM-DD HH:mm:ss');
                    // let bDatetime = bookmark.datetime ? bookmark.datetime : moment().format('YYYY-MM-DD HH:mm:ss');
                    const eBDatetime = existBookmark.datetime ?? moment().format('YYYY-MM-DD HH:mm:ss');
                    const bDatetime = bookmark.datetime ?? moment().format('YYYY-MM-DD HH:mm:ss');

                    existBookmark.datetime = eBDatetime <= bDatetime ? eBDatetime : bDatetime;
                    // console.log("已存在书签url为空，书签的url也为空。", existBookmark, bookmark);
                    // 先处理新文件夹下的书签，最后合并到已存在的文件夹中
                    cleanupBookmarks(bookmark.children, pathSet, bookmark);
                    // console.log("合并的两个书签：", existBookmark, bookmark);
                    // existBookmark.children = existBookmark.children.concat(bookmark.children);
                    existBookmark.children.push(...bookmark.children);
                    // console.log("合并后的书签", existBookmark);
                    needDelBookmarkIndex.push(i);
                }
                else {
                    // 如果书签中的url存在，则说明已存在的是文件夹，新的书签是书签
                    bookmark.title = bookmark.title + "_1";
                    bookmark.path = bookmark.path + "_1";
                }
            }
            else {
                // 如果已存在的书签中的url不为空，则说明这是个书签
                if (bookmark.url) {
                    // 如果新的书签url也不为空，说明新的也是书签
                    if (existBookmark.url !== bookmark.url) {
                        // 如果两个书签的url不同，则按照时间决定修改哪个书签的名字
                        // 有url的书签必定是书签，不是文件夹
                        if ((existBookmark.datetime ?? "") >= (bookmark.datetime ?? "")) {
                            existBookmark.title = existBookmark.title + "_1";
                            existBookmark.path = existBookmark.path + "_1";
                        }
                        else {
                            bookmark.title = bookmark.title + "_1";
                            bookmark.path = bookmark.path + "_1";
                        }
                    }
                    else {
                        // 如果两个书签url相同，则删除时间更晚的那个书签
                        // 逻辑上直接将已存在的书签的时间改成更早的时间即可
                        // console.log("两个书签url相同。", existBookmark, bookmark);
                        needDelBookmarkIndex.push(i);
                        if ((existBookmark.datetime ?? "") >= (bookmark.datetime ?? "")) {
                            existBookmark.datetime = bookmark.datetime;
                        }
                    }
                } else {
                    console.error("未处理的情况，existBookmark：", existBookmark, "bookmark：",  bookmark);
                }
            }
        }
        else {
            pathSet[bookmark.path] = bookmark;
            if (!bookmark.parent && parent) {
                // 如果书签的父节点不存在，则添加父节点
                bookmark.parent = parent;
            }
            if (bookmark.children) {
                // 如果书签有子节点，则递归处理
                cleanupBookmarks(bookmark.children, pathSet, bookmark);
            }
        }
    });
    for (let index of Array.from(needDelBookmarkIndex).reverse()) {
        let bookmark = bookmarks[index];
        // console.log("要删除的书签", bookmark);
        bookmarks.splice(index, 1);
    }
    return bookmarks
}


/**
 * 获取书签根节点
 * @param bookmarks
 */
function getBookmarksRoot(bookmarks: Bookmark[] | Bookmark): Bookmark | null {
    if (!bookmarks) {
        return null
    }
    let bookmark: Bookmark | null = null
    if (Array.isArray(bookmarks)) {
        bookmark = bookmarks[0];
    }
    else {
        bookmark = bookmarks;
    }
    // if (!bookmark.parent) {
    //     return bookmark;
    // }
    // return getBookmarksRoot(bookmark.parent)
    while (bookmark && bookmark.parent) {
        bookmark = bookmark.parent;
    }

    return bookmark;
}


/**
 * 序列化书签
 * @param bookmarks
 */
function dumpBookmarksJSON(bookmarks: Bookmark[]): string {
    let root = getBookmarksRoot(bookmarks);
    if (!root) {
        // console.error("获取收藏夹的根出错。", bookmarks)
        throw Error("获取收藏夹的根出错。")
    }
    // console.log("root", root);
    return JSON.stringify(root.toObj())
}


/**
 * 反序列化书签
 * @param bookmarksJson
 */
function loadBookmarksJSON(bookmarksJson: string): Bookmark[] {
    let obj = JSON.parse(bookmarksJson);
    // console.log("obj", obj);
    let bookmark = Bookmark.fromObject(obj);
    // console.log("bookmark", bookmark);
    return bookmark.children[0].children
}


/**
 * 合并两个书签
 * @param mainBookmarks
 * @param otherBookmarks
 */
function mergeBookmarks(mainBookmarks: Bookmark[], ...otherBookmarks: Bookmark[][]): Bookmark[] {
    let mainParent = mainBookmarks[0].parent ?? null;
    let mergeBookmarks: Bookmark[] = [];
    if (!mainParent) {
        mergeBookmarks = mainBookmarks.concat(otherBookmarks.reduce((acc, curr) => acc.concat(curr), []));
    }
    else {
        mainParent.children.concat(otherBookmarks.reduce((acc, curr) => acc.concat(curr), []));
        mergeBookmarks = mainParent.children;
        mergeBookmarks.forEach((bookmark) => {
            bookmark.parent = mainParent;
        })
    }
    console.log("mergeBookmarks mergeBookmarks", mergeBookmarks);
    let pathSet = {};
    cleanupBookmarks(mergeBookmarks, pathSet, mainParent);
    console.log("mergeBookmarks pathSet", pathSet);
    return mergeBookmarks;
}

// /**
//  * 合并两个书签
//  * @param aBookmarks
//  * @param bBookmarks
//  */
// function mergeBookmarks(aBookmarks: Bookmark[], bBookmarks: Bookmark[]): Bookmark[] {
//     let aParent = null;
//     if (aBookmarks.length && aBookmarks[0].parent) {
//         aParent = aBookmarks[0].parent;
//     }
//     let aBmMap: Record<string, Bookmark> = {};
//     cleanupBookmarks(aBookmarks, aBmMap, aParent);
//     _MergeBBookmarks(aBmMap, bBookmarks);
//     return aBookmarks;
// }
//
// /**
//  *
//  * @param aBmMap
//  * @param bBookmarks
//  */
// function _MergeBBookmarks(aBmMap: Record<string, Bookmark>, bBookmarks: Bookmark[]) {
//     for (let bBookmark of bBookmarks) {
//         if (hasProperty(aBmMap, bBookmark.path)) {
//
//         }
//         else {
//
//         }
//     }
// }


/**
 * 比较两个书签列表的区别
 * @param mainBookmarks
 * @param otherBookmarks
 * @return mainAddPathSet main新增的部分
 * @return mainDelPathSet main删除的部分
 */
function diffBookmarks(mainBookmarks: Bookmark[], otherBookmarks: Bookmark[]): {
    mainAddPathSet: Record<string, Bookmark>,
    mainDelPathSet: Record<string, Bookmark>,
} {
    const mainPathSet: Record<string, Bookmark> = {};
    // const mainParent = mainBookmarks && mainBookmarks.length && mainBookmarks[0].parent ? mainBookmarks[0].parent : null;
    const mainParent = mainBookmarks?.[0]?.parent?? null;
    cleanupBookmarks(mainBookmarks, mainPathSet, mainParent);
    const otherPathSet: Record<string, Bookmark> = {};
    // const otherParent = otherBookmarks && otherBookmarks.length && otherBookmarks[0].parent ? otherBookmarks[0].parent : null;
    const otherParent = otherBookmarks?.[0]?.parent?? null;
    cleanupBookmarks(otherBookmarks, otherPathSet, otherParent);

    const mainAddPathSet: Record<string, Bookmark> = {};
    const mainDelPathSet: Record<string, Bookmark> = {};

    for (const key in mainPathSet) {
        if (!(key in otherPathSet)) {
            mainAddPathSet[key] = mainPathSet[key];
        }
    }

    for (const key in otherPathSet) {
        if (!(key in mainPathSet)) {
            mainDelPathSet[key] = otherPathSet[key];
        }
    }

    return {mainAddPathSet, mainDelPathSet};
}


function delBookmark(pathSet: Record<string, Bookmark>, delPath: string) {
    let delBookmark = pathSet[delPath];
    if (!delBookmark) {
        console.log("待删除的书签不存在：", delPath, pathSet, delBookmark)
        return;
    }
    if (!delBookmark.parent) {
        console.log("待删除的书签没有父书签", delBookmark);
        return
    }
    let parentBookmark: Bookmark[] = delBookmark.parent.children;
    const idx = parentBookmark.findIndex((bookmark) => bookmark.path === delBookmark.path);
    if (idx === -1) {
        console.log(`删除书签 未找到该书签${delPath}`, pathSet);
        return;
    }
    parentBookmark.splice(idx, 1);
}


function delBookmarks(pathSet: Record<string, Bookmark>, delPathArr: string[]) {
    for (let delPath of delPathArr) {
        delBookmark(pathSet, delPath);
    }
}


export {Bookmark, BookmarkObj, cleanupBookmarks, getBookmarkPath, dumpBookmarksJSON, loadBookmarksJSON, getBookmarksRoot, mergeBookmarks, diffBookmarks, delBookmark, delBookmarks};
